#include <Arduino.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "FastLED.h"
#include "OneButton.h"
#include <esp_task_wdt.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
// #define DEBUG //是否开启DEBUG串口输出模式
//////////////////////////////////////config//////////////////////////////////////
#define DD1 33 //灯带一号
#define DD2 27
#define DD3 13
#define DD4 21
#define DD5 17
#define DZ1 25 //点阵一号
#define DZ2 14
#define DZ3 4
#define DZ4 22
#define DZ5 5
#define DZR 19	//用于显示R的方形点阵接口处
#define DIN1 26 //振动传感器一号
#define DIN2 12
#define DIN3 16
#define DIN4 23
#define DIN5 18
#define AIN1 35 //用于接受振动传感器信息的模拟引脚，但是实际上并未被使用
#define AIN2 32
#define AIN3 34
#define AIN4 36
#define AIN5 39
#define BOOT 0 //板子上面的按键用于调试使用
#define PWM 15 //板子上原本要用于输出PWM的引脚,那个伏虎驱动板上,这个是LED可以用来调试
enum status
{
	OFF,		// OFF表征扇叶的熄灭状态
	HALF_LIGHT, // HALF_LIGHT表征扇叶的待激活状态（就是有一个箭头一直在闪烁的状态）
	LIGHT		// LIGHT表征扇叶的已激活状态
};
enum FAN_NUM
{
	FAN_0,
	FAN_1,
	FAN_2,
	FAN_3,
	FAN_4
};
int DD[5] = {DD1, DD2, DD3, DD4, DD5};		 //存放灯带引脚数据的数组
int DZ[6] = {DZ1, DZ2, DZ3, DZ4, DZ5, DZR};	 //存放点阵引脚数据的数组
int DIN[5] = {DIN1, DIN2, DIN3, DIN4, DIN5}; //存放振动传感器引脚数据的数组
int FAN_order[5] = {3, 2, 1, 4, 0};			 //这个亮灯的顺序固定下来在这个数组里面,等真的旋转起来的话,这个和随机的没设么两样
volatile int FAN_NUM = -1;					 //正在闪亮的扇叶编号
volatile int FAN_HIT = -1;					 //被击中的扇叶编号
int FANS[5] = {OFF};						 //正在亮着的扇叶的数组，经过和金力盟的讨论，如果使用多线程的话就不能只有两个状态，应该为三个状态，0：灭 1：半亮 2：全亮，然后使用那个线程来专门显示当前灯的状态
int color = CRGB::Green;					 //保存扇叶的颜色的变量，初始化为红色
TaskHandle_t handle_arrow;					 //任务函数的参照,用于控制任务启停
//////////////////////////////////////////////////////////////////////////////////
// 初始化WS2812B使用
// 此示例程序需要使用FastLED库
//////////////////////////////////////WS2812//////////////////////////////////////
#define NUM_Pentagon_dd 180 // 5条边的灯带的灯珠数量
#define NUM_trapezia_dd 140 //最上面的那个梯形的灯带的灯珠数量
#define NUM_dz 512
#define NUM_dz_dd NUM_dz + NUM_Pentagon_dd //长方形的点阵共有512(32*8+32*8)颗灯珠，他后面连着一段灯带这个灯带就是那个5边形的灯带，这一段也要加上基本上在200左右
#define NUM_dzR 256						   // R点阵的灯珠个数16*16
// Arduino输出控制信号引脚
#define LED_TYPE WS2812			// LED灯带型号
#define COLOR_ORDER GRB			// RGB灯珠中红色、绿色、蓝色LED的排列顺序
uint8_t max_bright = 150;		// LED亮度控制变量，可使用数值为 0 ～ 255， 数值越大则光带亮度越高
CRGB leds_dd1[NUM_trapezia_dd]; // 建立灯带leds
CRGB leds_dd2[NUM_trapezia_dd];
CRGB leds_dd3[NUM_trapezia_dd];
CRGB leds_dd4[NUM_trapezia_dd];
CRGB leds_dd5[NUM_trapezia_dd];
CRGB leds_dz1[NUM_dz_dd];
CRGB leds_dz2[NUM_dz_dd];
CRGB leds_dz3[NUM_dz_dd];
CRGB leds_dz4[NUM_dz_dd];
CRGB leds_dz5[NUM_dz_dd];
CRGB leds_dzR[NUM_dzR];
////////////////////////////////////////函数声明区////////////////////////////////////////
//单个扇叶待打击状态num是扇叶编号
void half_light(int num);
//单个扇叶完全点亮状态num是扇叶编号
void full_light(int num);
//单个扇叶熄灭num是扇叶编号
void turn_off_light(int num);
//用于在点阵上面显示箭头的函数
void ArrowDz(CRGB *leds_dz);
//将FANS数组中的所有数字全部置零，即熄灭所有灯
void fans_all_off();
//将FANS数组中的所有数字全部置1，即使所有的扇叶都处于待激活状态
void fans_all_half_light();
//将FANS数组中的所有数字全部置2，即点亮所有灯
void fans_all_light();
//灯条灯带初始化函数   ---加入到setup函数
void light_setup();
//用于显示箭头
void Arrow(int num);
//单个扇叶待打击状态num是扇叶编号
void fans_all_half_light();
//单个扇叶完全点亮状态num是扇叶编号
void full_light(int num);
void LAR(CRGB *leds_dz, int num); // lightArrow
//单个扇叶熄灭num是扇叶编号
void turn_off_light(int num);
//////////////////////////////////////WS2812//////////////////////////////////////
void light_setup() //灯条灯带初始化函数   ---加入到setup函数
{
	LEDS.addLeds<LED_TYPE, DD1, COLOR_ORDER>(leds_dd1, NUM_trapezia_dd); // 初始化灯带
	LEDS.addLeds<LED_TYPE, DD2, COLOR_ORDER>(leds_dd2, NUM_trapezia_dd); // 初始化灯带
	LEDS.addLeds<LED_TYPE, DD3, COLOR_ORDER>(leds_dd3, NUM_trapezia_dd); // 初始化灯带
	LEDS.addLeds<LED_TYPE, DD4, COLOR_ORDER>(leds_dd4, NUM_trapezia_dd); // 初始化灯带
	LEDS.addLeds<LED_TYPE, DD5, COLOR_ORDER>(leds_dd5, NUM_trapezia_dd); // 初始化灯带
	LEDS.addLeds<LED_TYPE, DZ1, COLOR_ORDER>(leds_dz1, NUM_dz_dd);		 // 初始化点阵
	LEDS.addLeds<LED_TYPE, DZ2, COLOR_ORDER>(leds_dz2, NUM_dz_dd);		 // 初始化点阵
	LEDS.addLeds<LED_TYPE, DZ3, COLOR_ORDER>(leds_dz3, NUM_dz_dd);		 // 初始化点阵
	LEDS.addLeds<LED_TYPE, DZ4, COLOR_ORDER>(leds_dz4, NUM_dz_dd);		 // 初始化点阵
	LEDS.addLeds<LED_TYPE, DZ5, COLOR_ORDER>(leds_dz5, NUM_dz_dd);		 // 初始化点阵
	LEDS.addLeds<LED_TYPE, DZR, COLOR_ORDER>(leds_dzR, NUM_dzR);		 // 初始化R点阵
}
void lt(int num)
{
	fill_solid(leds_dzR + num, 1, color);
}
void ltd(int num)
{
	fill_solid(leds_dzR + num, 1, CRGB::Black);
}
void lt_lot(int num1, int num2, int num3, int num4, int num5, int num6, int num7, int num8, int num9, int num10, int num11, int num12, int num13)
{
	fill_solid(leds_dzR + num1, 1, color);
	fill_solid(leds_dzR + num2, 1, color);
	fill_solid(leds_dzR + num3, 1, color);
	fill_solid(leds_dzR + num4, 1, color);
	fill_solid(leds_dzR + num5, 1, color);
	fill_solid(leds_dzR + num6, 1, color);
	fill_solid(leds_dzR + num7, 1, color);
	fill_solid(leds_dzR + num8, 1, color);
	fill_solid(leds_dzR + num9, 1, color);
	fill_solid(leds_dzR + num10, 1, color);
	fill_solid(leds_dzR + num11, 1, color);
	fill_solid(leds_dzR + num12, 1, color);
	fill_solid(leds_dzR + num13, 1, color);
}
void R_light()
{
	for (int i = 0; i <= 6; i++)
	{
		lt_lot(18 + 32 * i, 19 + 32 * i, 20 + 32 * i, 21 + 32 * i, 22 + 32 * i, 23 + 32 * i, 24 + 32 * i, 25 + 32 * i, 26 + 32 * i, 27 + 32 * i, 28 + 32 * i, 29 + 32 * i, 30 + 32 * i);
		lt_lot(33 + 32 * i, 34 + 32 * i, 35 + 32 * i, 36 + 32 * i, 37 + 32 * i, 38 + 32 * i, 39 + 32 * i, 40 + 32 * i, 41 + 32 * i, 42 + 32 * i, 43 + 32 * i, 44 + 32 * i, 45 + 32 * i);
	}
	lt(1);
	lt(13);
	lt(145);
	lt(174);
	lt(177);
	lt(176);
	lt(207);
	for (int i = 0; i <= 6; i++)
		ltd(22 + i);
	ltd(36);
	ltd(37);
	ltd(58);
	for (int i = 0; i <= 1; i++)
	{
		ltd(131 + i * 32);
		ltd(132 + i * 32);
		ltd(133 + i * 32);
		ltd(154 + i * 32);
		ltd(155 + i * 32);
		ltd(156 + i * 32);
	}
	ltd(99);
	ltd(123);
	ltd(124);
	for (int i = 0; i <= 4; i++)
	{
		ltd(82 + i);
		ltd(105 + i);
		ltd(75 + i);
		ltd(112 + i);
		ltd(139 + i);
		ltd(213 + i);
		ltd(230 + i);
	}
	ltd(87);
	ltd(229);
	ltd(235);
	ltd(200);
	ltd(201);
	ltd(78);
	ltd(205);
	ltd(206);
	ltd(210);
	ltd(237);
	ltd(222);
	ltd(225);
	ltd(226);
	lt(115);
	lt(140);
	lt(141);
	lt(217);
	FastLED.show();
}
void LAR(CRGB *leds_dz, int num) // lightArrow
{
	fill_solid(leds_dz + num, 1, color);
}
void ArrowDz(CRGB *leds_dz)
{
	for (int i = 0; i <= 9; i++) ///第一段
	{
		LAR(leds_dz, 0 + 48 * i);
		LAR(leds_dz, 1 + 48 * i);
		LAR(leds_dz, 6 + 48 * i);
		LAR(leds_dz, 7 + 48 * i);
		LAR(leds_dz, 9 + 48 * i);
		LAR(leds_dz, 10 + 48 * i);
		LAR(leds_dz, 13 + 48 * i);
		LAR(leds_dz, 14 + 48 * i);
		LAR(leds_dz, 18 + 48 * i);
		LAR(leds_dz, 19 + 48 * i);
		LAR(leds_dz, 20 + 48 * i);
		LAR(leds_dz, 21 + 48 * i);
		LAR(leds_dz, 27 + 48 * i);
		LAR(leds_dz, 28 + 48 * i);
	}
	// LAR(leds_dz, 0 + 48 * 11);
	// LAR(leds_dz, 1 + 48 * 11);
	// LAR(leds_dz, 6 + 48 * 11);
	// LAR(leds_dz, 7 + 48 * 11);
	// LAR(leds_dz, 9 + 48 * 11);
	// LAR(leds_dz, 10 + 48 * 11);
	// LAR(leds_dz, 13 + 48 * 11);
	// LAR(leds_dz, 14 + 48 * 11);
	// LAR(leds_dz, 18 + 48 * 11);
	// LAR(leds_dz, 19 + 48 * 11);
	// LAR(leds_dz, 20 + 48 * 11);
	// LAR(leds_dz, 21 + 48 * 11);
	// LAR(leds_dz, 27 + 48 * 11);
	// LAR(leds_dz, 28 + 48 * 11);
	FastLED.show();
	vTaskDelay(75);
	fill_solid(leds_dz, 512, CRGB::Black);
	//////////////////////////////////////////////
	for (int i = 0; i <= 9; i++) ///第二段
	{
		LAR(leds_dz, 0 + 48 * i + 8);
		LAR(leds_dz, 1 + 48 * i + 8);
		LAR(leds_dz, 6 + 48 * i + 8);
		LAR(leds_dz, 7 + 48 * i + 8);
		LAR(leds_dz, 9 + 48 * i + 8);
		LAR(leds_dz, 10 + 48 * i + 8);
		LAR(leds_dz, 13 + 48 * i + 8);
		LAR(leds_dz, 14 + 48 * i + 8);
		LAR(leds_dz, 18 + 48 * i + 8);
		LAR(leds_dz, 19 + 48 * i + 8);
		LAR(leds_dz, 20 + 48 * i + 8);
		LAR(leds_dz, 21 + 48 * i + 8);
		LAR(leds_dz, 27 + 48 * i + 8);
		LAR(leds_dz, 28 + 48 * i + 8);
	}
	// LAR(leds_dz, 0 + 48 * 11 + 8);
	// LAR(leds_dz, 1 + 48 * 11 + 8);
	// LAR(leds_dz, 6 + 48 * 11 + 8);
	// LAR(leds_dz, 7 + 48 * 11 + 8);
	// LAR(leds_dz, 9 + 48 * 11 + 8);
	// LAR(leds_dz, 10 + 48 * 11 + 8);
	// LAR(leds_dz, 13 + 48 * 11 + 8);
	// LAR(leds_dz, 14 + 48 * 11 + 8);
	// LAR(leds_dz, 18 + 48 * 11 + 8);
	// LAR(leds_dz, 19 + 48 * 11 + 8);
	// LAR(leds_dz, 20 + 48 * 11 + 8);
	// LAR(leds_dz, 21 + 48 * 11 + 8);
	FastLED.show();
	vTaskDelay(75);
	fill_solid(leds_dz, 512, CRGB::Black);
	//////////////////////////////////////////////
	for (int i = 0; i <= 9; i++) ///第三段
	{
		LAR(leds_dz, 0 + 48 * i + 16);
		LAR(leds_dz, 1 + 48 * i + 16);
		LAR(leds_dz, 6 + 48 * i + 16);
		LAR(leds_dz, 7 + 48 * i + 16);
		LAR(leds_dz, 9 + 48 * i + 16);
		LAR(leds_dz, 10 + 48 * i + 16);
		LAR(leds_dz, 13 + 48 * i + 16);
		LAR(leds_dz, 14 + 48 * i + 16);
		LAR(leds_dz, 18 + 48 * i + 16);
		LAR(leds_dz, 19 + 48 * i + 16);
		LAR(leds_dz, 20 + 48 * i + 16);
		LAR(leds_dz, 21 + 48 * i + 16);
		LAR(leds_dz, 27 + 48 * i + 16);
		LAR(leds_dz, 28 + 48 * i + 16);
	}
	// LAR(leds_dz, 0 + 48 * 11 + 16);
	// LAR(leds_dz, 1 + 48 * 11 + 16);
	// LAR(leds_dz, 6 + 48 * 11 + 16);
	// LAR(leds_dz, 7 + 48 * 11 + 16);
	// LAR(leds_dz, 9 + 48 * 11 + 16);
	// LAR(leds_dz, 10 + 48 * 11 + 16);
	// LAR(leds_dz, 13 + 48 * 11 + 16);
	// LAR(leds_dz, 14 + 48 * 11 + 16);

	FastLED.show();
	vTaskDelay(75);
	fill_solid(leds_dz, 512, CRGB::Black);
	//////////////////////////////////////////////
	LAR(leds_dz, 3);
	LAR(leds_dz, 4);
	for (int i = 0; i <= 9; i++) ///第四段
	{
		LAR(leds_dz, 0 + 48 * i + 24);
		LAR(leds_dz, 1 + 48 * i + 24);
		LAR(leds_dz, 6 + 48 * i + 24);
		LAR(leds_dz, 7 + 48 * i + 24);
		LAR(leds_dz, 9 + 48 * i + 24);
		LAR(leds_dz, 10 + 48 * i + 24);
		LAR(leds_dz, 13 + 48 * i + 24);
		LAR(leds_dz, 14 + 48 * i + 24);
		LAR(leds_dz, 18 + 48 * i + 24);
		LAR(leds_dz, 19 + 48 * i + 24);
		LAR(leds_dz, 20 + 48 * i + 24);
		LAR(leds_dz, 21 + 48 * i + 24);
		LAR(leds_dz, 27 + 48 * i + 24);
		LAR(leds_dz, 28 + 48 * i + 24);
	}
	// LAR(leds_dz, 0 + 48 * 11 + 24);
	// LAR(leds_dz, 1 + 48 * 11 + 24);
	// LAR(leds_dz, 6 + 48 * 11 + 24);
	// LAR(leds_dz, 7 + 48 * 11 + 24);

	FastLED.show();
	vTaskDelay(75);
	fill_solid(leds_dz, 512, CRGB::Black);
	//////////////////////////////////////////////
	LAR(leds_dz, 2);
	LAR(leds_dz, 3);
	LAR(leds_dz, 4);
	LAR(leds_dz, 5);
	LAR(leds_dz, 3 + 8);
	LAR(leds_dz, 4 + 8);
	for (int i = 0; i <= 9; i++) ///第五段
	{
		LAR(leds_dz, 0 + 48 * i + 32);
		LAR(leds_dz, 1 + 48 * i + 32);
		LAR(leds_dz, 6 + 48 * i + 32);
		LAR(leds_dz, 7 + 48 * i + 32);
		LAR(leds_dz, 9 + 48 * i + 32);
		LAR(leds_dz, 10 + 48 * i + 32);
		LAR(leds_dz, 13 + 48 * i + 32);
		LAR(leds_dz, 14 + 48 * i + 32);
		LAR(leds_dz, 18 + 48 * i + 32);
		LAR(leds_dz, 19 + 48 * i + 32);
		LAR(leds_dz, 20 + 48 * i + 32);
		LAR(leds_dz, 21 + 48 * i + 32);
		LAR(leds_dz, 27 + 48 * i + 32);
		LAR(leds_dz, 28 + 48 * i + 32);
	}

	FastLED.show();
	vTaskDelay(75);
	fill_solid(leds_dz, 512, CRGB::Black);
	//////////////////////////////////////////////
	LAR(leds_dz, 1);
	LAR(leds_dz, 2);
	LAR(leds_dz, 5);
	LAR(leds_dz, 6);
	LAR(leds_dz, 2 + 8);
	LAR(leds_dz, 3 + 8);
	LAR(leds_dz, 4 + 8);
	LAR(leds_dz, 5 + 8);
	LAR(leds_dz, 3 + 16);
	LAR(leds_dz, 4 + 16);
	for (int i = 0; i <= 9; i++) ///第六段
	{
		LAR(leds_dz, 0 + 48 * i + 40);
		LAR(leds_dz, 1 + 48 * i + 40);
		LAR(leds_dz, 6 + 48 * i + 40);
		LAR(leds_dz, 7 + 48 * i + 40);
		LAR(leds_dz, 9 + 48 * i + 40);
		LAR(leds_dz, 10 + 48 * i + 40);
		LAR(leds_dz, 13 + 48 * i + 40);
		LAR(leds_dz, 14 + 48 * i + 40);
		LAR(leds_dz, 18 + 48 * i + 40);
		LAR(leds_dz, 19 + 48 * i + 40);
		LAR(leds_dz, 20 + 48 * i + 40);
		LAR(leds_dz, 21 + 48 * i + 40);
		LAR(leds_dz, 27 + 48 * i + 40);
		LAR(leds_dz, 28 + 48 * i + 40);
	}
	LAR(leds_dz, 0 + 59 * 8);
	LAR(leds_dz, 1 + 59 * 8);
	LAR(leds_dz, 6 + 59 * 8);
	LAR(leds_dz, 7 + 59 * 8);
	LAR(leds_dz, 9 + 59 * 8);
	LAR(leds_dz, 10 + 59 * 8);
	LAR(leds_dz, 13 + 59 * 8);
	LAR(leds_dz, 14 + 59 * 8);
	LAR(leds_dz, 18 + 59 * 8);
	LAR(leds_dz, 19 + 59 * 8);
	LAR(leds_dz, 20 + 59 * 8);
	LAR(leds_dz, 21 + 59 * 8);
	LAR(leds_dz, 27 + 59 * 8);
	LAR(leds_dz, 28 + 59 * 8);
	FastLED.show();
	vTaskDelay(75);
	fill_solid(leds_dz, NUM_dz, CRGB::Black);
}
//用于显示箭头
void Arrow(int num)
{
	switch (num)
	{
	case FAN_0:
		//点阵呈箭头
		ArrowDz(leds_dz1);
		break;
	case FAN_1:
		//点阵呈箭头
		ArrowDz(leds_dz2);
		break;
	case FAN_2:
		//点阵呈箭头
		ArrowDz(leds_dz3);
		break;
	case FAN_3:
		//点阵呈箭头
		ArrowDz(leds_dz4);
		break;
	case FAN_4:
		//点阵呈箭头
		ArrowDz(leds_dz5);
		break;
	default:
		break;
	}
}
/////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////定时器相关函数区////////////////////////////////////////
float last_s = 2.5; // 2.5秒
hw_timer_t *timer;
int order = 0;
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
volatile bool state = 0;
void IRAM_ATTR random_turn_on_a_light()
{
	portENTER_CRITICAL(&mux);
	timerWrite(timer, 0); // 重置定时器，喂狗 (feed watchdog)
	for (int i = 0; i < 5; i++)
	{
		if (FANS[i] == HALF_LIGHT)
		{
			FANS[i] = OFF;
			// vTaskSuspend(handle_arrow); //暂停箭头任务
		}
		else
		{
			continue;
		}
	}
	if (order == 5)
	{
		order = 0;
	}
	state = !state;
	digitalWrite(2, state);
	FAN_NUM = FAN_order[order++];
	FANS[FAN_NUM] = HALF_LIGHT; //将扇叶数组中的这个待激活状态的扇叶置为一，将会在单独的一个线程中显示待激活的状态
	// vTaskResume(handle_arrow);  //重启箭头任务
	portEXIT_CRITICAL(&mux);
}
void IRAM_ATTR all_fans_restart() // 中断函数
{
	fans_all_off();
	random_turn_on_a_light();
}
////////////////////////////////////////并未使用到下面的函数////////////////////////////////////////
//按照规范的流程开始传入的这个timer定时器
void start_timer(hw_timer_t *timer)
{
	timer = timerBegin(0, 80, true);							// 使用硬件定时器0建立1微秒周期的计时器 采用80倍分频将定时器的80MHz分至1MHz ESP32共有4个定时器
	timerAttachInterrupt(timer, &random_turn_on_a_light, true); // 链接中断服务函数
	timerAlarmWrite(timer, last_s * 1000000, true);				// 这里数字的单位是微秒，由于上面我们80倍频的原因
	timerAlarmEnable(timer);									// 使能启动定时器
}
//按照规范的流程停止传入的这个timer定时器
void stop_timer(hw_timer_t *timer)
{
	if (timer != NULL) //确认timer存在
	{
		// Serial.println("Stop Timer!"); //串口打印停止定时器
		timerAlarmDisable(timer);	 //取消timer定时器
		timerDetachInterrupt(timer); //解除timer的中断
		timerEnd(timer);			 //结束timer
		timer = NULL;				 //代表可回收timer的内存
	}
}
//重新启动定时器
void restart_timer(hw_timer_t *timer)
{
	stop_timer(timer);
	start_timer(timer);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////能量机关单个扇叶点亮////////////////////////////////////////
// CHSV my_hsv_color(0,255,255);
//仅仅只是操作数组而已
void fans_all_half_light()
{
	for (int i = 0; i < 5; i++)
	{
		FANS[i] = HALF_LIGHT;
	}
}
void fans_all_light()
{
	for (int i = 0; i < 5; i++)
	{
		FANS[i] = LIGHT;
	}
}
//将FANS数组中的所有数字全部置零，即熄灭所有灯
void fans_all_off()
{
	for (int i = 0; i < 5; i++)
	{
		FANS[i] = OFF;
	}
}
//单个扇叶待打击状态num是扇叶编号
void half_light(int num)
{
#ifdef DEBUG
	Serial.printf("We are half_light %d\n\r", num);
#endif
	// digitalWrite(PWM, HIGH);
	switch (num)
	{
	case FAN_0:
		// fill_sold section全部点亮/熄灭，没有时间差
		fill_solid(leds_dd1, NUM_trapezia_dd, color);
		FastLED.show();
		break;
	case FAN_1:
		// fill_sold section全部点亮/熄灭，没有时间差
		fill_solid(leds_dd2, NUM_trapezia_dd, color);
		FastLED.show();
		break;
	case FAN_2:
		// fill_sold section全部点亮/熄灭，没有时间差
		fill_solid(leds_dd3, NUM_trapezia_dd, color);
		FastLED.show();
		break;
	case FAN_3:
		// fill_sold section全部点亮/熄灭，没有时间差
		fill_solid(leds_dd4, NUM_trapezia_dd, color);
		FastLED.show();
		break;
	case FAN_4:
		// fill_sold section全部点亮/熄灭，没有时间差
		fill_solid(leds_dd5, NUM_trapezia_dd, color);
		FastLED.show();
		break;
	default:
		break;
	}
}
//单个扇叶完全点亮状态num是扇叶编号
void full_light(int num)
{
#ifdef DEBUG
	Serial.printf("We are full_light %d\n\r", num);
#endif
	switch (num)
	{
	case FAN_0:
		// fill_sold section全部点亮/熄灭，没有时间差
		fill_solid(leds_dd1, NUM_trapezia_dd, color);
		fill_solid(leds_dz1, NUM_dz_dd, color);
		FastLED.show();
		break;
	case FAN_1:
		fill_solid(leds_dd2, NUM_trapezia_dd, color);
		fill_solid(leds_dz2, NUM_dz_dd, color);
		FastLED.show();
		break;
	case FAN_2:
		fill_solid(leds_dd3, NUM_trapezia_dd, color);
		fill_solid(leds_dz3, NUM_dz_dd, color);
		FastLED.show();
		break;
	case FAN_3:
		fill_solid(leds_dd4, NUM_trapezia_dd, color);
		fill_solid(leds_dz4, NUM_dz_dd, color);
		FastLED.show();
		break;
	case FAN_4:
		fill_solid(leds_dd5, NUM_trapezia_dd, color);
		fill_solid(leds_dz5, NUM_dz_dd, color);
		FastLED.show();
		break;
	default:
		break;
	}
}
//单个扇叶熄灭num是扇叶编号
void turn_off_light(int num)
{
#ifdef DEBUG
	Serial.printf("turn_off_light%d ", num);
#endif
	// digitalWrite(PWM, LOW);
	switch (num)
	{
	case FAN_0:
		// fill_sold section全部点亮/熄灭，没有时间差
		fill_solid(leds_dd1, NUM_trapezia_dd, CRGB::Black);
		fill_solid(leds_dz1, NUM_dz_dd, CRGB::Black);
		FastLED.show();
		break;
	case FAN_1:
		fill_solid(leds_dd2, NUM_trapezia_dd, CRGB::Black);
		fill_solid(leds_dz2, NUM_dz_dd, CRGB::Black);
		FastLED.show();
		break;
	case FAN_2:
		fill_solid(leds_dd3, NUM_trapezia_dd, CRGB::Black);
		fill_solid(leds_dz3, NUM_dz_dd, CRGB::Black);
		FastLED.show();
		break;
	case FAN_3:
		fill_solid(leds_dd4, NUM_trapezia_dd, CRGB::Black);
		fill_solid(leds_dz4, NUM_dz_dd, CRGB::Black);
		FastLED.show();
		break;
	case FAN_4:
		fill_solid(leds_dd5, NUM_trapezia_dd, CRGB::Black);
		fill_solid(leds_dz5, NUM_dz_dd, CRGB::Black);
		FastLED.show();
		break;
	default:
		break;
	}
}
////////////////////////////////////////振动传感器相关中断函数区////////////////////////////////////////
void hit_init() //初始化为可触发状态
{
	FAN_HIT = -1;
}
#ifdef DEBUG
void IRAM_ATTR ISR_FANS_DEBUG()
{
	hit_alarming = true; //触发已经击中扇叶
	FAN_HIT = 0;		 //被击中的是0号扇叶
	Serial.println("BOOT button hit!");
}
#endif
//////////////////////////////////////////////////////////////////////////////////
// 初始化OneButton使用
// 此示例程序需要使用OneButton库
//////////////////////////////////////OneButton///////////////////////////////////
int DebounceTicks = 10;						 // 显式设置在一次点击被假定稳定之前必须经过的毫秒数。
int ClickTicks = 200;						 // 显式设置在检测到单击之前必须经过的毫秒数。
OneButton DIN0_button(DIN[0], false, false); // 实例化一个OneButton对象
OneButton DIN1_button(DIN[1], false, false); // 实例化一个OneButton对象
OneButton DIN2_button(DIN[2], false, false); // 实例化一个OneButton对象
OneButton DIN3_button(DIN[3], false, false); // 实例化一个OneButton对象
OneButton DIN4_button(DIN[4], false, false); // 实例化一个OneButton对象
//单击
void click(void *parameter)
{
	portENTER_CRITICAL(&mux);
	FAN_HIT = (int)parameter;
	// Serial.printf("FAN_HIT is:%d\n", FAN_HIT);
	timerWrite(timer, 0); // 重置定时器，喂狗 (feed watchdog)
	// Serial.printf("FAN_HIT is:%d\tFAN_NUM is%d\n", FAN_HIT, FAN_NUM);
	if (FAN_HIT == FAN_NUM)
	{
		// Serial.println("ISR_FANS_4");
		FANS[FAN_HIT] = LIGHT; //被正确击中的扇叶变为2，即该扇叶可以完全点亮
	}
	else
	{
		fans_all_off();
	}
	for (int i = 0; i < 5; i++)
	{
		if (FANS[i] == HALF_LIGHT)
		{
			FANS[i] = OFF;
			// vTaskSuspend(handle_arrow); //暂停箭头任务
		}
		else
		{
			continue;
		}
	}
	if (order == 5)
	{
		order = 0;
	}
	state = !state;
	digitalWrite(2, state);
	FAN_NUM = FAN_order[order++];
	FANS[FAN_NUM] = HALF_LIGHT; //将扇叶数组中的这个待激活状态的扇叶置为一，将会在单独的一个线程中显示待激活的状态
	hit_init();					//重新初始化所有的扇叶为可触发状态
	portEXIT_CRITICAL(&mux);
}
///////////////////////////////多线程任务函数区///////////////////////////////
//循环保持点亮数组中有效的已被点亮的扇叶
void Task_Change_FANS(void *pvParam)
{
	//这个函数只是负责显示而已，只要数组中的数字满足显示的条件即可显示
	while (true)
	{
		for (int i = 0; i < 5; i++)
		{
			switch (FANS[i])
			{
			case HALF_LIGHT:
				half_light(i);
				break;
			case LIGHT:
				full_light(i);
				// Serial.println("FULL LIGHT!");
				break;
			case OFF:
				turn_off_light(i);
				break;
			default:
				break;
			}
		}
		vTaskDelay(1);
#ifdef DEBUG
		// Serial.println(hitTime);
		// vTaskDelay(500);
		Serial.println(); //换行
#endif
	}
}
void Task_Arrow_FANS(void *pvParam)
{
	while (true)
	{
		for (int i = 0; i < 5; i++)
		{
			switch (FANS[i])
			{
			case HALF_LIGHT:
				//点阵呈箭头
				Arrow(i);
				break;
			case LIGHT:
				full_light(i);
				break;
			default:
				break;
			}
		}
		vTaskDelay(1);
#ifdef DEBUG
		// Serial.println(hitTime);
		// vTaskDelay(500);
		Serial.println(); //换行
#endif
	}
}
//////////////////////////////硬件初始化//////////////////////////////
void setup()
{
	randomSeed(analogRead(AIN1)); //使用一个未被使用到的引脚产生随机数种子
	// disableCore0WDT();
	// disableCore1WDT();
	pinMode(2, OUTPUT);	  //配置2号引脚为输出引脚，用于点亮板子内置的LED灯
	pinMode(PWM, OUTPUT); //配置15号引脚为输出引脚,这里原本是留给PWM输出用的,不过没用上,再伏虎驱动板上面这是一个LED
	// pinMode(DIN[0], INPUT_PULLDOWN); //配置0号振动传感器  一定要下拉一下不能是悬空的状态，否则会输入值有可能会一直跳变
	// pinMode(DIN[1], INPUT_PULLDOWN); //配置1号振动传感器
	// pinMode(DIN[2], INPUT_PULLDOWN); //配置2号振动传感器
	// pinMode(DIN[3], INPUT_PULLDOWN); //配置3号振动传感器
	// pinMode(DIN[4], INPUT_PULLDOWN); //配置4号振动传感器
	pinMode(BOOT, INPUT); //配置BOOT按键为输入模式
	Serial.begin(115200);
	// /////////////////////////////////WS2812//////////////////////////////////////////////////////////
	light_setup();					   //灯条灯带初始化函数   ---加入到setup函数
	FastLED.setBrightness(max_bright); // 设置灯带亮度
	R_light();						   //点亮R点阵
	////////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////定时器相关////////////////////////////////////////
	//启动定时器
	timer = timerBegin(0, 80, true);					  // 使用硬件定时器0建立1微秒周期的计时器 采用80倍分频将定时器的80MHz分至1MHz ESP32共有4个定时器
	timerAttachInterrupt(timer, &all_fans_restart, true); // 链接中断服务函数
	timerAlarmWrite(timer, last_s * 1000000, true);		  // 这里数字的单位是微秒，由于上面我们80倍频的原因
	timerAlarmEnable(timer);							  // 使能启动定时器
#ifdef DEBUG
	Serial.println("Start Timer!");
#endif
	/////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////设置振动传感器相关的中断服务////////////////////////////////////////
	DIN0_button.reset(); //清除一下按钮状态机的状态
	DIN0_button.setDebounceTicks(DebounceTicks);
	DIN0_button.setClickTicks(ClickTicks);
	DIN0_button.attachClick(click, (void *)0);

	DIN1_button.reset(); //清除一下按钮状态机的状态
	DIN1_button.setDebounceTicks(DebounceTicks);
	DIN1_button.setClickTicks(ClickTicks);
	DIN1_button.attachClick(click, (void *)1);

	DIN2_button.reset(); //清除一下按钮状态机的状态
	DIN2_button.setDebounceTicks(DebounceTicks);
	DIN2_button.setClickTicks(ClickTicks);
	DIN2_button.attachClick(click, (void *)2);

	DIN3_button.reset(); //清除一下按钮状态机的状态
	DIN3_button.setDebounceTicks(DebounceTicks);
	DIN3_button.setClickTicks(ClickTicks);
	DIN3_button.attachClick(click, (void *)3);

	DIN4_button.reset(); //清除一下按钮状态机的状态
	DIN4_button.setDebounceTicks(DebounceTicks);
	DIN4_button.setClickTicks(ClickTicks);
	DIN4_button.attachClick(click, (void *)4);
#ifdef DEBUG
	attachInterrupt(BOOT, ISR_FANS_DEBUG, FALLING); //配置BOOT按键为下降沿触发
#endif
	///////////////////////////////多线程初始化//////////////////////////////////////////////////////////
	xTaskCreate(Task_Change_FANS, "Task_Change_FANS", 10000, NULL, 1, NULL);		//启动按照FANS数组中的状态去显示当前各个扇叶的任务
	xTaskCreate(Task_Arrow_FANS, "Task_Arrow_FANS", 10000, NULL, 1, &handle_arrow); //启动按照FANS数组中的状态去显示当前箭头的任务
}
void loop()
{
	DIN0_button.tick();
	DIN1_button.tick();
	DIN2_button.tick();
	DIN3_button.tick();
	DIN4_button.tick();
}